using System;
using System.Collections.Generic;
using Firestarter.DB.Schema.BO;
using Firestarter.DB_DomainModel.Logic;
using FireStarterModeller.BO;
using FireStarterModeller.Test.BO;
using Habanero.Base.Exceptions;
using NUnit.Framework;

namespace Firestarter.DB_DomainModel.Logic.Test
{
    [TestFixture]
    public class TestCreateSchemaTable : TestBase

    {
        [Test]
        public void Test_CreateSchemaTable()
        {
            //---------------Set up test pack-------------------

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            DBTable info = new DBTable("tableName");
            //---------------Test Result -----------------------
            Assert.AreEqual("tableName", info.TableName);
        }

        [Test]
        public void Test_CreateDMClass()
        {
            //---------------Set up test pack-------------------

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            string boname = "BOName";
            DMClass info = new DMClass {ClassNameBO = boname};
            //---------------Test Result -----------------------
            Assert.AreEqual(boname, info.ClassNameBO);
            Assert.IsFalse(info.Generated.Value, "Generated should default to false");
        }

        [Test]
        public void Test_SaveSchemaTable()
        {
            //---------------Set up test pack-------------------
            DBTable info = new DBTable("tableName");
            DBDatabase dbDatabase = new DBDatabase();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            dbDatabase.DatabaseName = "some name";
            info.Database = dbDatabase;
            dbDatabase.Save();
            info.Save();
            //---------------Test Result -----------------------
            Assert.AreEqual("tableName", info.TableName);
        }

        [Test]
        public void Test_SaveDMSolution_SavedDMClass()
        {
            //---------------Set up test pack-------------------
            string boname = "BOName";
            DMClass dmClass = new DMClass {ClassNameBO = boname};
            DMSolution dmSolution = new DMSolution();
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, dmSolution.Assemblies.Count);
            //---------------Execute Test ----------------------
            //dmClass.Solution = dmSolution;
            dmSolution.SolutionName = "test";
            dmSolution.SolutionDirectory = "fdafdafasd";
            dmClass.Assembly = new DMAssembly {Name = "Somename", Solution = dmSolution};
            dmSolution.DefaultAssembly = dmClass.Assembly;
            //dmClass.Assembly.SolutionID = dmSolution.SolutionID; //TODO consider why this cannot be done in a relationship
            // I think it should be possible speak to peter
            //WTODO Brett 03 Feb 2009:

            //dmClass.CreateObjectIdentity(TestUtilsShared.CreateUnsavedValidDMProperty(dmClass));
            dmSolution.Save();
            //---------------Test Result -----------------------
            Assert.AreEqual(boname, dmClass.ClassNameBO);
            Assert.AreEqual(1, dmSolution.Assemblies.Count);
            Assert.IsFalse(dmSolution.Status.IsNew);
            Assert.IsFalse(dmClass.Status.IsNew);
            Assert.IsFalse(dmClass.Assembly.Status.IsNew);
        }

        //TODO Brett 20 Jan 2009: Move this test to its own test project when hageshen finished converting
        [Test]
        public void Test_PrimaryKeyInfo_Columns()
        {
            //---------------Set up test pack-------------------
            DBColumn dbColumn = new DBColumn("SomeColName");
            DBPrimaryKey dbPrimaryKey = new DBPrimaryKey();
            dbPrimaryKey.AddColumnInfo(dbColumn);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dbPrimaryKey.PrimaryKeyColumns.Count);
            //---------------Execute Test ----------------------
            IList<DBColumn> columnInfos = dbPrimaryKey.Columns;
            //---------------Test Result -----------------------
            Assert.AreEqual(1, columnInfos.Count);
            Assert.AreSame(dbColumn, columnInfos[0]);
        }

        [Test]
        public void Test_PrimaryKeyInfo_AddColumnInfo_AddColWithSameNameButDiffObject()
        {
            //---------------Set up test pack-------------------
            DBColumn dbColumn = new DBColumn("SomeColName");
            DBPrimaryKey dbPrimaryKey = new DBPrimaryKey();
            dbPrimaryKey.AddColumnInfo(dbColumn);

            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dbPrimaryKey.PrimaryKeyColumns.Count);
            //---------------Execute Test ----------------------
            try
            {
                dbPrimaryKey.AddColumnInfo(new DBColumn("SomeColName"));
                Assert.Fail("expected Err");
            }
                //---------------Test Result -----------------------
            catch (HabaneroDeveloperException ex)
            {
                StringAssert.Contains("A column with name", ex.Message);
                StringAssert.Contains("was could not be added to the primary key for the business object", ex.Message);
                StringAssert.Contains
                    ("was could not be added to the primary key for the business object", ex.DeveloperMessage);
            }
        }

        [Test]
        public void Test_CreateProjectAssembly()
        {
            //---------------Set up test pack-------------------

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            const string expectedAssemblyName = "SomeName";
            DMAssembly assembly = new DMAssembly(expectedAssemblyName);
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedAssemblyName, assembly.Name);
            //TODO  21 Jan 2009: Change assembly.Name to AssemblyName in firestarter
        }

        [Test]
        public void Test_CreateProjectInfo()
        {
            //---------------Set up test pack-------------------

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            const string expectedProjectName = "SomeName";
            DMSolution dmSolution = new DMSolution(expectedProjectName);
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedProjectName, dmSolution.SolutionName);
        }

        [Test]
        public void Test_KeyInfo_Columns()
        {
            //---------------Set up test pack-------------------
            DBColumn dbColumn = new DBColumn("SomeColName");
            DBKey dbKey = new DBKey();
            dbKey.AddColumnInfo(dbColumn);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dbKey.KeyColumns.Count);
            //---------------Execute Test ----------------------
            IList<DBColumn> columnInfos = dbKey.Columns;
            //---------------Test Result -----------------------
            Assert.AreEqual(1, columnInfos.Count);
            Assert.AreSame(dbColumn, columnInfos[0]);
        }

        [Test]
        public void Test_KeyInfo_AddColumnInfo_AddColWithSameNameButDiffObject()
        {
            //---------------Set up test pack-------------------
            DBColumn dbColumn = new DBColumn("SomeColName");
            DBKey dbKey = new DBKey();
            dbKey.AddColumnInfo(dbColumn);

            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dbKey.KeyColumns.Count);
            //---------------Execute Test ----------------------
            try
            {
                dbKey.AddColumnInfo(new DBColumn("SomeColName"));
                Assert.Fail("expected Err");
            }
                //---------------Test Result -----------------------
            catch (HabaneroDeveloperException ex)
            {
                StringAssert.Contains("A dbColumn with name", ex.Message);
                StringAssert.Contains(" could not be added to the Key Info for the business object", ex.Message);
                StringAssert.Contains
                    (" could not be added to the Key Info for the business object", ex.DeveloperMessage);
            }
        }

        [Test]
        public void Test_UniqueConstraint_Properties()
        {
            //---------------Set up test pack-------------------
            DMProperty dmProperty = new DMProperty {PropertyName = "SomeColName"};
            DMUniqueConstraint constraint = new DMUniqueConstraint();
            constraint.AddPropertyInfo(dmProperty);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, constraint.UniqueConstraintProperties.Count);
            //---------------Execute Test ----------------------
            IList<DMProperty> columnInfos = constraint.Properties;
            //---------------Test Result -----------------------
            Assert.AreEqual(1, columnInfos.Count);
            Assert.AreSame(dmProperty, columnInfos[0]);
        }

        [Test]
        public void Test_UniqueConstraint_GetPropertyInfo()
        {
            //---------------Set up test pack-------------------
            DMProperty expectedDMProperty = new DMProperty {PropertyName = "SomeColName"};
            DMUniqueConstraint constraint = new DMUniqueConstraint();
            constraint.AddPropertyInfo(expectedDMProperty);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, constraint.UniqueConstraintProperties.Count);
            //---------------Execute Test ----------------------
            DMProperty actualProperty = constraint.GetPropertyInfo(expectedDMProperty.PropertyName);
            //---------------Test Result -----------------------
            Assert.IsNotNull(actualProperty);
            Assert.AreEqual(expectedDMProperty, actualProperty);
        }

        [Test]
        public void Test_UniqueConstraint_GetKeyPropertyInfo()
        {
            //---------------Set up test pack-------------------
            DMProperty expectedDMProperty = new DMProperty {PropertyName = "SomeColName"};
            DMUniqueConstraint constraint = new DMUniqueConstraint();
            DMUniqueConstraintProperty expectedConstraintProp = constraint.AddPropertyInfo(expectedDMProperty);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, constraint.UniqueConstraintProperties.Count);
            //---------------Execute Test ----------------------
            DMUniqueConstraintProperty actualConstraintProperty = constraint.GetUniqueConstraintProperty
                (expectedDMProperty.PropertyName);
            //---------------Test Result -----------------------
            Assert.IsNotNull(actualConstraintProperty);
            Assert.AreEqual(expectedConstraintProp, actualConstraintProperty);
        }

        [Test]
        public void Test_AddPropertyToUniqueConstraint()
        {
            //---------------Set up test pack-------------------
            DMProperty dmProperty = new DMProperty {PropertyName = "SomeColName"};
            DMUniqueConstraint constraint = new DMUniqueConstraint();
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, constraint.Properties.Count);
            //---------------Execute Test ----------------------
            constraint.AddPropertyInfo(dmProperty);
            //---------------Test Result -----------------------
            Assert.AreEqual(1, constraint.Properties.Count);
        }

        [Test]
        public void Test_AddPropertyTwiceToUniqueConstraint_ShouldRaiseError()
        {
            //---------------Set up test pack-------------------
            DMProperty dmProperty = new DMProperty {PropertyName = "SomeColName"};
            DMUniqueConstraint constraint = new DMUniqueConstraint();
            DMUniqueConstraintProperty expectedConstraintProp = constraint.AddPropertyInfo(dmProperty);
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, constraint.Properties.Count);
            Assert.AreEqual(1, constraint.UniqueConstraintProperties.Count);
            //---------------Execute Test ----------------------
            try
            {
                DMUniqueConstraintProperty actualConstraintProp = constraint.AddPropertyInfo(dmProperty);
                Assert.Fail("expected Err");
            }
                //---------------Test Result -----------------------
            catch (HabaneroDeveloperException ex)
            {
                StringAssert.Contains
                    ("could not be added to the Alternate Key Info for the business object", ex.Message);
            }
        }

        [Test]
        public void Test_UniqueConstraint_AddPropertyInfoInfo_AddColWithSameNameButDiffObject()
        {
            //---------------Set up test pack-------------------
            DMProperty property = new DMProperty {PropertyName = "SomeColName"};
            DMUniqueConstraint constraint = new DMUniqueConstraint();
            constraint.AddPropertyInfo(property);

            //---------------Assert Precondition----------------
            Assert.AreEqual(1, constraint.Properties.Count);
            Assert.AreEqual(1, constraint.UniqueConstraintProperties.Count);
            //---------------Execute Test ----------------------
            try
            {
                constraint.AddPropertyInfo(new DMProperty {PropertyName = "SomeColName"});
                Assert.Fail("expected Err");
            }
                //---------------Test Result -----------------------
            catch (HabaneroDeveloperException ex)
            {
                StringAssert.Contains("A property with name", ex.Message);
                StringAssert.Contains
                    (" could not be added to the Alternate Key Info for the business object", ex.Message);
                StringAssert.Contains
                    (" could not be added to the Alternate Key Info for the business object", ex.DeveloperMessage);
            }
        }


        [Test]
        public void Test_FindBOPropertyBasedOnColumnId_BOHasNoColumns()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = new DMClass();
            //---------------Assert Precondition----------------
            Assert_HasNoProperties(dmClass);
            //---------------Execute Test ----------------------
            DMProperty property = dmClass.FindBOPropertyByColumnId(Guid.NewGuid());
            //---------------Test Result -----------------------
            Assert.IsNull(property);
        }

        private static void Assert_HasNoProperties(DMClass dmClass)
        {
            Assert.AreEqual(0, dmClass.Properties.Count);
        }

        private static void Assert_HasOneProperties(DMClass dmClass)
        {
            Assert.AreEqual(1, dmClass.Properties.Count);
        }

        private static void Assert_HasTwoProperties(DMClass dmClass)
        {
            Assert.AreEqual(2, dmClass.Properties.Count);
        }

        [Test]
        public void Test_FindBOPropertyBasedOnColumnId_BODoesNotHaveTheRequiredColumn()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = new DMClass();
            dmClass.Properties.CreateBusinessObject();
            //---------------Assert Precondition----------------
            Assert_HasOneProperties(dmClass);
            //---------------Execute Test ----------------------
            DMProperty property = dmClass.FindBOPropertyByColumnId(Guid.NewGuid());
            //---------------Test Result -----------------------
            Assert.IsNull(property);
        }

        [Test]
        public void Test_FindBOPropertyBasedOnColumnId_BODoesHaveTheRequiredColumn()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = new DMClass();
            DMProperty expectedProperty = dmClass.Properties.CreateBusinessObject();
            Guid columnID = Guid.NewGuid();
            expectedProperty.MappedDBColumnID = columnID;
            //---------------Assert Precondition----------------
            Assert_HasOneProperties(dmClass);
            //---------------Execute Test ----------------------
            DMProperty foundProperty = dmClass.FindBOPropertyByColumnId(columnID);
            //---------------Test Result -----------------------
            Assert.IsNotNull(foundProperty);
            Assert.AreSame(expectedProperty, foundProperty);
        }

        [Test]
        public void Test_FindBOPropertyBasedOnColumnId_BOHas2Props_DoesHaveTheRequiredColumn()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = new DMClass();
            dmClass.Properties.CreateBusinessObject();
            DMProperty expectedProperty = dmClass.Properties.CreateBusinessObject();
            Guid columnID = Guid.NewGuid();
            expectedProperty.MappedDBColumnID = columnID;
            //---------------Assert Precondition----------------
            Assert_HasTwoProperties(dmClass);
            //---------------Execute Test ----------------------
            DMProperty foundProperty = dmClass.FindBOPropertyByColumnId(columnID);
            //---------------Test Result -----------------------
            Assert.IsNotNull(foundProperty);
            Assert.AreSame(expectedProperty, foundProperty);
        }

        [Test]
        public void Test_TableInfo_MappedBusinessObject_IsNull()
        {
            //---------------Set up test pack-------------------
            DMClass dmClass = new DMClass();
            //---------------Assert Precondition----------------
            Assert.IsNull(dmClass.MappedTableID);
            //---------------Execute Test ----------------------
            var actualMappedTable = dmClass.MappedTable;
            //---------------Test Result -----------------------
            Assert.IsNull(actualMappedTable, "The mapped table should not be null");
        }

        [Test]
        public void Test_TableInfo_MappedBusinessObject()
        {
            //---------------Set up test pack-------------------
            DBColumn dbColumn = new DBColumn("Some Column");
            DBTable dbTable = new DBTable("Some Table");
            dbTable.Columns.Add(dbColumn);
            DBToDMClassImporter boImporter = new DBToDMClassImporter();
            DMClass dmClass = boImporter.Import(TestUtilsDMSolution.CreateSavedDMSolution(), dbTable);
            //---------------Assert Precondition----------------
            Assert.IsNotNull(dmClass.MappedTableID);
            Assert.AreEqual(dbTable.TableID, dmClass.MappedTableID);
            //---------------Execute Test ----------------------
            var actualMappedTable = dmClass.MappedTable;
            //---------------Test Result -----------------------
            Assert.IsNotNull(actualMappedTable, "The mapped table should not be null");
            Assert.AreSame(dbTable, actualMappedTable);
        }
    }
}